#include <QMetaObject>
#include <QMetaProperty>
//#include <QDebug>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QStackedWidget>
#include <QSet>
#include <QQueue>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include "ConfigData.h"
#include "ConfigEditor.h"
#include "config/ConfigItem.h"
#include "SwitchButton.h"
#include "ConfigSearchBar.h"



ConfigEditor::ConfigEditor(ConfigDataModel *data, QWidget *parent)
    : QWidget(parent)
{


    m_data = data;
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    QHBoxLayout *headLine = new QHBoxLayout;
    headLine->addStretch();
    switchButton = new SwitchButton;
    headLine->addWidget(switchButton);
    headLine->addStretch();
    mainLayout->addLayout(headLine);
    mainLayout->addSpacing(20);

    stackWidget = new QStackedWidget(this);
    stackWidget->setContentsMargins(10, 10, 10, 10);
    mainLayout->addWidget(stackWidget);
    mainLayout->addSpacing(20);

    QFormLayout *layout = new QFormLayout;

    layout->addRow(tr("Search"), new ConfigSearchBar(data, this));

    QPushButton *updateBtn = new QPushButton;
    updateBtn->setText(tr("Update"));
    layout->addRow(updateBtn->text(), updateBtn);
    connect(updateBtn, &QPushButton::clicked, this, [=](){
        this->updateAllConfig(UpdateOption::Item);
    });

    QLineEdit *filePath = new QLineEdit;
    layout->addRow(tr("File Path"), filePath);

    QPushButton *loadBtn = new QPushButton;
    loadBtn->setText(tr("Load"));
    layout->addRow(loadBtn->text(), loadBtn);
    connect(loadBtn, &QPushButton::clicked, this, [=](){
        m_data->readFromFile(filePath->text());
    });

    QPushButton *saveBtn = new QPushButton;
    saveBtn->setText(tr("Save"));
    layout->addRow(saveBtn->text(), saveBtn);
    connect(saveBtn, &QPushButton::clicked, this, [=](){
        m_data->writeToFile(filePath->text());
    });

    mainLayout->addLayout(layout);
    this->setLayout(mainLayout);


    QQueue<ConfigDataModel*> models;
    models.enqueue(data);

    while (!models.isEmpty())
    {
        ConfigDataModel *model = models.dequeue();
        const QMetaObject *obj = model->metaObject();
        QWidget *w = new QWidget;
        QFormLayout *formLayout = new QFormLayout(w);
        formLayout->setHorizontalSpacing(20);
        formLayout->setVerticalSpacing(20);
        w->setLayout(formLayout);
        stackWidget->addWidget(w);
        switchButton->append(model->translatedName);
        for (int i = obj->propertyOffset(); i < obj->propertyCount(); i++)
        {
            QMetaProperty property = obj->property(i);
            if (property.read(model).canConvert<ConfigItem*>())
            {
                ConfigItem *item = property.read(model).value<ConfigItem*>();
                QWidget *content = item->createRelatedWidget();
                if (content != nullptr)
                {
                    formLayout->addRow(item->translatedName, content);
                }
            }
            else if (property.read(model).canConvert<ConfigDataModel*>())
            {
                models.enqueue(property.read(model).value<ConfigDataModel*>());
            }
        }
    }

    connect(switchButton, &SwitchButton::indexChanged, stackWidget, &QStackedWidget::setCurrentIndex);
//    QFormLayout *layout = new QFormLayout(this);
//    layout->setHorizontalSpacing(20);
//    layout->setVerticalSpacing(20);
//    const QMetaObject *obj = data->metaObject();
//    for (int i = obj->propertyOffset(); i < obj->propertyCount(); i++)
//    {
//        QMetaProperty property = obj->property(i);
//        if (property.read(data).canConvert<ConfigItem*>())
//        {
//            ConfigItem *item = property.read(m_data).value<ConfigItem*>();
//            QWidget *content = item->createRelatedWidget();
//            if (content != nullptr)
//            {
//                layout->addRow(item->translatedName, content);
//            }
//        }
//    }

    // updateAllConfig(UpdateOption::WidgetContent);

}

ConfigEditor::~ConfigEditor()
{
}

void ConfigEditor::updateAllConfig(UpdateOption option)
{
    const QMetaObject *obj = m_data->metaObject();
    for (int i = obj->propertyOffset(); i < obj->propertyCount(); i++)
    {
        QMetaProperty property = obj->property(i);
        if (property.read(m_data).canConvert<ConfigItem*>())
        {
            ConfigItem *item = property.read(m_data).value<ConfigItem*>();
            QWidget *content = stackWidget->findChild<QWidget*>(item->objectName());
            if (content != nullptr)
            {
                item->updateItem(content, option);
            }
        }
    }
}
// BUG: update this
void ConfigEditor::updateOneConfig(QWidget *widget) // 更新配置项
{
    const QMetaObject *obj = m_data->metaObject();
    for (int i = obj->propertyOffset(); i < obj->propertyCount(); i++)
    {
        QMetaProperty property = obj->property(i);
        if (property.name() == widget->objectName())
        {
            ConfigItem *item = property.read(m_data).value<ConfigItem*>();
            if (item != nullptr)
            {
                item->updateItem(widget, UpdateOption::Item);
            }
            break;
        }
    }
}

void ConfigEditor::updateOneConfig(ConfigItem *item, UpdateOption ops) // 更新控件内容
{
    if (item != nullptr)
    {
        QWidget *content = this->findChild<QWidget*>(item->objectName());
        if (content != nullptr)
        {
            item->updateItem(content, ops);
        }
    }
}

void ConfigEditor::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(QPen(QColor(200, 200, 200), 2));
    QRect frame = stackWidget->rect();
    frame.moveTo(stackWidget->pos());
    painter.drawRoundedRect(frame, 10, 10);
    QWidget::paintEvent(event);
}





